import Logger from "@/utils/logger";
import validateConnection from "@/views/workTable/edges/validateConnection";
import {portCommonAttr, portCommonAttr_disable, portCommonAttr_using} from '../port/portConfig'

const EventDataBus = {}

export const NonTargetEdgeCreate = {
  mouseenter(e, graph) {
    // EventDataBus.backupTarget = e.edge.getTarget()
  },

  mousemove(e, graph) {
    // EventDataBus.isDrag = true
  },

  mouseleave(e, graph) {
    // if (!EventDataBus.isDrag) {
    //   Logger.log('未触发边拖动事件，边空终点事件取消')
    //   return
    // }
    //
    // const sourceCell = graph.getCellById(e.edge.source.cell)
    // if (sourceCell.shape !== 'abtest') {
    //   Logger.log('不是需要手动设置target的节点类型')
    //   return
    // }
    //
    // Logger.log('触发边拖动事件，释放后查找终点')
    // const {edge} = e
    //
    // const targetAnchor = e.view.targetAnchor
    // const targetViews = graph.findViewsFromPoint(targetAnchor.x, targetAnchor.y)
    // if (!targetViews.length) {
    //   Logger.log('边终点没有可用节点')
    //   return
    // }
    //
    // const targetView = targetViews[targetViews.length - 1] // 取最上面的
    // if (targetView && !(targetView instanceof NodeView)) {
    //   Logger.log('不是节点类型的节点')
    //   return
    // }
    //
    // const targetCell = targetView.cell
    //
    // const targetInPorts = targetCell.getPortsByGroup('in')
    // if (!targetInPorts.length) {
    //   Logger.log('边终点没有可用入桩')
    //   return
    // }
    //
    // // 清空初始的途经点
    // edge.setVertices([])
    //
    // // getPortsByGroup('in')[0] 目前in 连接桩只有一个所以取0，未来如果出现多个又想精确定位，这里要重新处理
    // edge.setTarget({
    //   cell: targetCell.id,
    //   port: targetCell.getPortsByGroup('in')[0].id,
    // })
    //
    // EventDataBus.isDrag = false
    //
    // const validateConnectEvent = {
    //   edge: e.edge,
    //   edgeView: e.view,
    //   sourceCell: graph.getCellById(e.edge.source.cell),
    //   sourceMagnet: e.view.sourceMagnet,
    //   sourcePort: e.cell.source.port,
    //   sourceView: e.view.sourceView,
    //   targetCell: graph.getCellById(e.edge.target.cell),
    //   targetMagnet: e.view.targetMagnet,
    //   targetPort: e.cell.target.port,
    //   targetView: targetView,
    //   type: 'target',
    // }
    //
    // if (!validateConnection(validateConnectEvent, graph)) {
    //   Logger.log('无目标节点设置目标验证连接未通过')
    // }
  },

  edgemoving(e, graph) {
  },

  edgemoved(e, graph) {
    const sourceCell = graph.getCellById(e.edge.source.cell)
    if (sourceCell.shape !== 'abtest') {
      return
    }
    const views = graph.findViewsFromPoint(e.x, e.y)
    const view = views.filter(view => view.cell.shape.indexOf('edge') === -1)[0]

    if (!view) {
      return
    }
    const targetCell = view.cell
    if (!targetCell) {
      return
    }
    // console.log('targetCell', targetCell)

    const incomingEdges = graph.getIncomingEdges(targetCell) || []
    // console.log('incomingEdges', incomingEdges)
    let targetPortId
    if (incomingEdges.length) {
      targetPortId = incomingEdges[0].targetPort
    } else {
      targetPortId = targetCell.getPorts()[0].id
    }
    // console.log('targetPortId', targetPortId)
    e.edge.setVertices([])
    e.edge.setTarget({
      cell: targetCell.id,
      port: targetPortId,
    })
  }
}

export const DeleteIconVisibleEvent = {
  mouseenter(e) {
    const sourceCell = e.edge.getSourceCell()
    const shape = sourceCell.shape
    if (shape === 'abtest') {
      return
    }

    // e.edge.addTools({
    //   name: 'button-remove',
    //   args: { distance: -40 },
    // })
    e.edge.addTools({
      name: 'delete-item'
    })
  },

  mouseleave(e) {
    // 删除按钮隐藏
    e.edge.removeTool('delete-item')
  }
}

export const SegmentsToolVisible = {
  edgemouseenter(e) {
    e.edge.addTools({
      name: 'segments',
      args: {
        snapRadius: 10,
        attrs: {
          fill: '#C7CDDB',
        },
      },
    })
  },

  edgemouseleave(e) {
    e.edge.removeTool('segments')
  }
}

/**
 * 边调整工具Segments 依赖edge的vertices
 * 路由manhatthan 与 工具Segments 冲突
 * 手动设置边的vertices 以支持工具Segments
 */
export const SupportSegmentTool = {
  setVertices({edge, edgeView}, graph) {
    edge.setVertices(edgeView.routePoints)
  },

  nodemousedown(e, graph) {
    const connectedEdges = graph.getConnectedEdges(e.cell)
    connectedEdges.forEach(edge => {
      edge.setVertices([])
    })
  },

  nodemouseup(e, graph) {
    const connectedEdges = graph.getConnectedEdges(e.cell)
    connectedEdges.forEach(edge => {
      this.setVertices({
        edge,
        edgeView: graph.findViewByCell(edge)
      }, graph)
    })
  },

  edgeconnected(e, graph) {
    this.setVertices({
      edge: e.edge,
      edgeView: e.view
    })
  }
}

/**
 * 边连接后检查Port 以启用或禁用
 * e.g. 开始节点仅允许 一条出边 拉出边之后禁用其他Port
 **/
export const TogglePortStatus = {
  edgeconnected(e, graph) {
    Logger.log('连接了一条边...edge:connected triggered...')
    const {
      sourceCell,
      targetCell,
    } = this.getCellInfo({edge: e.edge, graph})

    this.sourceConnectedRule[sourceCell.shape] && this.sourceConnectedRule[sourceCell.shape](e, graph)
    this.targetConnectedRule[targetCell.shape] && this.targetConnectedRule[targetCell.shape](e, graph)
  },

  edgeremoved(e, graph) {
    Logger.log('移除了边...edge:removed triggered')
    const {
      sourceCell,
      targetCell,
    } = this.getCellInfo({edge: e.edge, graph})
    sourceCell && this.sourceRemovedRule[sourceCell.shape] && this.sourceRemovedRule[sourceCell.shape](e, graph)
    targetCell && this.targetRemovedRule[targetCell.shape] && this.targetRemovedRule[targetCell.shape](e, graph)
  },

  getCellInfo({edge, graph}) {
    try {
      const sourceCell = graph.getCellById(edge.source.cell)
      const sourceCellPortIds = sourceCell && sourceCell.getPorts().map(item => item.id) || []
      const sourceCellConnectedEdges = graph.getConnectedEdges(sourceCell) || []
      const sourceCellUsingPorts = sourceCellPortIds.filter(portId => {
        return sourceCellConnectedEdges.find(edge => edge.source.port === portId || edge.target.port === portId)
      })
      const sourceCellUnUsingPorts = sourceCellPortIds.filter(portId => !sourceCellUsingPorts.includes(portId))

      const targetCell = graph.getCellById(edge.target.cell)
      const targetCellPortIds = targetCell && targetCell.getPorts().map(item => item.id) || []
      const targetCellConnectedEdges = graph.getConnectedEdges(targetCell) || []
      const targetCellUsingPorts = targetCellPortIds.filter(portId => {
        return targetCellConnectedEdges.find(edge => edge.source.port === portId || edge.target.port === portId)
      })
      const targetCellUnUsingPorts = targetCellPortIds.filter(portId => !targetCellUsingPorts.includes(portId))

      return {
        sourceCell,
        sourceCellPortIds,
        sourceCellConnectedEdges,
        sourceCellUsingPorts,
        sourceCellUnUsingPorts,
        targetCell,
        targetCellPortIds,
        targetCellConnectedEdges,
        targetCellUsingPorts,
        targetCellUnUsingPorts
      }
    } catch (e) {
      console.error(e)
    }
  },

  // 节点作为起点连接
  sourceConnectedRule: {
    start(e, graph) {
      const {
        sourceCell,
        sourceCellUnUsingPorts
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})

      Logger.log('edge:connected: 根据【开始】节点规则 修改了Port属性')
      sourceCellUnUsingPorts.forEach(portId => {
        sourceCell.setPortProp(portId, ['attrs'], portCommonAttr_disable)
      })
      sourceCell.setPortProp(e.edge.source.port, ['attrs'], portCommonAttr_using)
    },

    condition(e, graph) {
      const {
        sourceCell,
        sourceCellUnUsingPorts
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})

      Logger.log('edge:connected: 根据【条件判断】节点规则 修改了Port属性')
      sourceCell.setPortProp(e.edge.source.port, ['attrs'], portCommonAttr_using)

      if (sourceCellUnUsingPorts.length <= 1) {
        sourceCellUnUsingPorts.forEach(portId => {
          sourceCell.setPortProp(portId, ['attrs'], portCommonAttr_disable)
        })
      }
    },

    wait(e, graph) {
      Logger.log('edge:connected: 根据【等待】节点规则 修改了Port属性')
      const {
        sourceCell,
        sourceCellUnUsingPorts,
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})

      sourceCell.setPortProp(e.edge.source.port, ['attrs'], portCommonAttr_using)
    }
  },

  // 节点作为终点连接
  targetConnectedRule: {
    condition(e, graph) {
      const {
        targetCell,
        targetCellUnUsingPorts
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})

      if (targetCellUnUsingPorts.length <= 1) {
        targetCellUnUsingPorts.forEach(portId => {
          targetCell.setPortProp(portId, ['attrs'], portCommonAttr_disable)
        })
      }
    },

    wait(e, graph) {
      Logger.log('edge:connected: 根据【等待】节点规则 修改了Port属性')

    }
  },

  // 节点作为起点边被移除
  sourceRemovedRule: {
    start(e, graph) {
      Logger.log('开始节点作为边的source被移除时, port的显示规则')

      const {
        sourceCell
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})
      sourceCell.getPorts().map(item => item.id).forEach(portId => {
        sourceCell.setPortProp(portId, ['attrs'], portCommonAttr)
      })
    },

    condition(e, graph) {
      const {
        sourceCell,
        sourceCellUnUsingPorts
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})
      sourceCell.setPortProp(e.edge.source.port, ['attrs'], portCommonAttr)
      sourceCellUnUsingPorts.forEach(portId => {
        sourceCell.setPortProp(portId, ['attrs'], portCommonAttr)
      })
    },

    wait(e, graph) {
      const {
        sourceCell,
        sourceCellUnUsingPorts
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})
      sourceCell.setPortProp(e.edge.source.port, ['attrs'], portCommonAttr)
      sourceCellUnUsingPorts.forEach(portId => {
        sourceCell.setPortProp(portId, ['attrs'], portCommonAttr)
      })
    }
  },

  // 节点作为终点边被移除
  targetRemovedRule: {
    start(e, graph) {
      Logger.log('开始节点作为边的target被移除时, port的显示规则 ===》 无具体规则')
    },

    condition(e, graph) {
      Logger.log('条件节点作为边的target被移除时, port的显示规则')

      const {
        targetCell,
        targetCellUnUsingPorts
      } = TogglePortStatus.getCellInfo({edge: e.edge, graph})

      targetCell.setPortProp(e.edge.target.port, ['attrs'], portCommonAttr)
      targetCellUnUsingPorts.forEach(portId => {
        targetCell.setPortProp(portId, ['attrs'], portCommonAttr)
      })
    }
  }
}

export const DeleteEdge = {
  edgedblclick(e, graph) {
    ElMessageBox.confirm('您双击了一条边，是否想要删除', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
    }).then(() => {
      graph.removeCell(e.edge)
    }).catch(() => {
      Logger.log('用户取消删除')
    })
  },
}

/**
 * 空白边创建后创建后自动创建 占位节点
 * @type {{edgeconnected(*, *): void}}
 */
export const CreatePlaceholderNode = {
  isEdgeJustAdded: false,


  edgeadded(e, graph) {
    Logger.log('添加了一条边, 确认是否需要创建占位节点...')
    this.isEdgeJustAdded = true
  },

  edgemouseleave(e, graph) {
    if (!this.isEdgeJustAdded) {
      return
    }

    if (e.view.targetView) {
      Logger.log('不需要创建占位节点...')
      return
    }
    this.isEdgeJustAdded = false
    Logger.log('终点为空，创建占位节点...')

    // 创建placeholderNode
    const placeholderNode = graph.addNode({
      shape: 'placeholder',
    })
    const pNodeRect = placeholderNode.size() // 宽高

    // 获取需要使用的Port group
    let startPoint, endPoint
    if (e.view.routePoints.length) {
      startPoint = e.view.routePoints[e.view.routePoints.length - 1]
    } else {
      startPoint = e.view.sourcePoint
    }
    endPoint = e.view.targetPoint

    let pNodePortGroup // placeholder节点 Port的朝向
    let pNodePosition = {x: 0, y: 0} // placeholder节点的坐标
    if (endPoint.x > startPoint.x) {
      pNodePortGroup = 'left'
      pNodePosition = {x: endPoint.x, y: endPoint.y - pNodeRect.height / 2}
    } else if (endPoint.x < startPoint.x) {
      pNodePortGroup = 'right'
      pNodePosition = {x: endPoint.x - pNodeRect.width, y: endPoint.y - pNodeRect.height / 2}
    } else if (endPoint.y > startPoint.y) {
      pNodePortGroup = 'top'
      pNodePosition = {x: endPoint.x - pNodeRect.width / 2, y: endPoint.y}
    } else {
      pNodePortGroup = 'bottom'
      pNodePosition = {x: endPoint.x - pNodeRect.width / 2, y: endPoint.y - pNodeRect.height}
    }

    placeholderNode.setPosition(pNodePosition)
    const portMetaData = placeholderNode.getPortsByGroup(pNodePortGroup)[0]
    e.edge.setTarget({
      cell: placeholderNode.id,
      port: portMetaData.id
    })
    graph.addNode(placeholderNode)
  }
}
